import { Injectable, Logger } from "@nestjs/common";
import { UploadService } from "~/modules/tools/upload/upload.service";
import { AccessHouseUploadDto } from "~/modules/assess/house/house.dto";
import { HouseEntity } from "~/modules/assess/house/house.entity";
import { InjectRepository } from "@nestjs/typeorm";
import { Repository } from "typeorm";
import { formatToDate } from "~/utils";
import { AccessDictService } from "../access-dict/access-dict.service";
import { AccessDictHouse } from "../access-dict/access-dict-house.entity";

@Injectable()
export class AccessHouseService {
	private readonly logger = new Logger(AccessHouseService.name)

	constructor(
		private readonly uploadService: UploadService,
		private readonly accessDictService: AccessDictService,
		@InjectRepository(HouseEntity)
		private readonly houseRepository: Repository<HouseEntity>,
	) {
	}

	/**
	 * 根据朝向角度获取房屋类型
	 * @param orientAngle
	 * @returns
	 */
	async getHouseTypeByOrientAngle(orientAngle: number): Promise<{ label: string, value: string }> {
		// 确保输入的角度在0到360度之间
		let degree = orientAngle % 360;

		if (degree < 0) {
			degree += 360;
		}

		const dictItems = await this.accessDictService.getHouseTypeDict()

		// 定义不同的角度区间及其对应的宅型，根据label返回对应的value
		if ((degree >= 337.5 && degree <= 360) || (degree >= 0 && degree < 22.5)) {
			return dictItems.find(item => item.label === '坎宅');
		} else if (degree >= 22.5 && degree < 67.5) {
			return dictItems.find(item => item.label === '艮宅');
		} else if (degree >= 67.5 && degree < 112.5) {
			return dictItems.find(item => item.label === '震宅');
		} else if (degree >= 112.5 && degree < 157.5) {
			return dictItems.find(item => item.label === '巽宅');
		} else if (degree >= 157.5 && degree < 202.5) {
			return dictItems.find(item => item.label === '离宅');
		} else if (degree >= 202.5 && degree < 247.5) {
			return dictItems.find(item => item.label === '坤宅');
		} else if (degree >= 247.5 && degree < 292.5) {
			return dictItems.find(item => item.label === '兑宅');
		} else if (degree >= 292.5 && degree < 337.5) {
			return dictItems.find(item => item.label === '乾宅');
		}
	}

	async save(accessHouseUploadDto: AccessHouseUploadDto, uid: number) {
		const path: string = await this.uploadService.saveFile(accessHouseUploadDto.file)

		// 业务逻辑
		const house = new HouseEntity()
		house.ownerName = accessHouseUploadDto.ownerName
		house.ownerBirth = accessHouseUploadDto.ownerBirth
		house.longitude = accessHouseUploadDto.longitude
		house.latitude = accessHouseUploadDto.latitude
		house.owner = { id: uid } as any
		house.url = path

		// 获取户型
		const houseType = await this.getHouseTypeByOrientAngle(accessHouseUploadDto.orientAngle)

		if (!houseType) {
			throw new Error('无当前房屋类型信息')
		}

		house.houseType = Number(houseType.value)
		house.orientAngle = accessHouseUploadDto.orientAngle

		return await this.houseRepository.save(house)
	}

	async getList(uid: number) {
		const rows: Record<string, any>[] = await this.houseRepository.find({ where: { owner: { id: uid } } })
		return rows.map((row: Record<string, any>) => {
			// 格式化时间 createdAt updatedAt ownerBirth，将 2024-07-13T14:46:08.135Z -> 2024-07-13 14:46:08
			row.createdAt = formatToDate(row.createdAt, 'YYYY-MM-DD HH:mm:ss')
			row.updatedAt = formatToDate(row.updatedAt, 'YYYY-MM-DD HH:mm:ss')
			row.ownerBirth = formatToDate(row.ownerBirth, 'YYYY-MM-DD HH:mm:ss')
			return row
		})
	}

	/**
	 * 根据房屋id获取房屋原始数据
	 * @param houseId
	 * @returns
	 */
	async getHouseOriginData(houseId: number): Promise<HouseEntity> {
		return await this.houseRepository.findOne({ where: { id: houseId } })
	}

	/**
	 * 根据id查找房屋信息
	 * @param id
	 * @returns
	 */
	async find(id: number): Promise<Record<string, any>> {
		const house: Record<string, any> = await this.houseRepository.createQueryBuilder('house')
			.leftJoinAndSelect('house.tags', 'tag')
			.where('house.id = :id', { id })
			.getOne();

		if (!house) {
			throw new Error('无当前房屋信息');
		}

		// 添加参数 houseTypeName, orientName
		// 判断是有有 houseType
		if (house.houseType) {
			house.houseTypeName = await this.accessDictService.transferDictValueToLabel('House', house.houseType.toString())
		}

		// 判断是否有 orient
		if (house.orient) {
			house.orientName = await this.accessDictService.transferDictValueToLabel('Direction', house.orient.toString())
		}

		// 时间格式化 createdAt updatedAt ownerBirth
		house.createdAt = formatToDate(house.createdAt, 'YYYY-MM-DD HH:mm:ss')
		house.updatedAt = formatToDate(house.createdAt, 'YYYY-MM-DD HH:mm:ss')
		house.ownerBirth = formatToDate(house.createdAt, 'YYYY-MM-DD HH:mm:ss')

		if (Array.isArray(house?.tags) && house.tags.length > 0) {
			house.tags = await Promise.all(house.tags.map(async tag => {
				if (tag.roomType) {
					tag.roomTypeName = await this.accessDictService.transferDictValueToLabel('Room', tag.roomType.toString())
				}

				if (tag.position) {
					tag.positionName = await this.accessDictService.transferDictValueToLabel('Direction', tag.position.toString())
				}

				tag.houseTypeName = house?.houseTypeName ?? ""

				return tag
			}))
		}

		return house
	}

	/**
	 * 根据房屋id获取房屋类型
	 * @param houseId
	 * @returns
	 */
	async getHouseTypeByHouseId(houseId: number): Promise<number> {
		const house: Record<string, any> = await this.getHouseOriginData(houseId)
		return Number(house.houseType)
	}

	/**
	 * 设置房屋分析和风水秘诀
	 * @param houseId
	 * @param orient
	 * @returns
	 */
	async setHouseAnylysisAndSecret(houseId: number, orient: number) {
		const house: HouseEntity = await this.getHouseOriginData(houseId)
		house.orient = orient
		// 根据 方位 和 宅型 获取分析结果和真绝描述，对应户型字典查询
		const accessHouseDict: AccessDictHouse = await this.accessDictService.getHouseAnalysisAndSecretDict(orient, house.houseType)
		house.realSecret = accessHouseDict.realSecret
		house.analysis = accessHouseDict.analysis

		return await this.houseRepository.save(house)
	}
}
